class SalaryJob < ApplicationJob
  queue_as :default

  def perform(companies, coaches, class_date_from, class_date_to)
    companies.delete("-1")
    coaches.delete("-1")
    cps = companies.blank? ? Company.pluck(:id) : companies.map(&:to_i)
    ccs = coaches.blank? ? Coach.pluck(:id) : coaches.map(&:to_i)
    ccs.each do |coach|
      coach_info = Coach.select(:id, :standard_lesson).find_by(id: coach)
      timetables = Timetable.includes(:company, :store, :course, :admission).where(
        class_start_time: class_date_from.to_date..(class_date_to.to_date + 1.days),
        status: [:released, :signed, :late, :absent],
        coach_id: coach,
        company_id: cps
      ).order(class_start_time: :asc)
      Payroll.where(coach_id: coach, company_id: cps, class_start_time: class_date_from.to_date..(class_date_to.to_date + 1.days)).delete_all
      standard_lesson_count = 0
      if timetables.present?
        cls = Coaches::Level.ransack(coach_id_eq: coach, office_start_at_lteq: (class_date_to.to_date + 1.days)).result.includes(:salaries)
        timetables.each { |timetable|
          #非正常签到处理
          i_quota, b_quota, deduction, copyright, grade, members, non_members = -1, 0, [], 0, 0, timetable.appointed_member.size, timetable.experience_member.size
          case timetable.course.usage
          when 'free', 'ordinary'
            _pricing, class_start_time, class_end_time, company_id, store_id = timetable.values_at(:pricing, :class_start_time, :class_end_time, :company_id, :store_id)
            copyright, grade, perquisite = %w(copyright,grade,perquisite).map { |key| _pricing.fetch(key, 0) }
            during = (class_end_time - class_start_time).to_i / 60
            ccls = cls.select { |clv| clv.course_id == timetable.course_id && class_start_time.to_date.between?(clv.office_start_at, clv.office_end_at) }
            salaries = ((ccls.detect { |clv| clv.store_id == timetable.store_id } ||
              ccls.detect { |clv| clv.store_id == -1 && clv.company_id == timetable.company_id } ||
              ccls.detect { |clv| clv.store_id == -1 && clv.company_id == -1 }).try(:salaries) ||
              [])
            fitted_salary = salaries.detect { |item| item.during == during } || salaries.detect { |item| item.during == -1 && during <= 75 }
            salary = fitted_salary.try(:price) || 0
            this_deduction = timetable.admission.try(:deduction)
            deduction << this_deduction.merge(type: 'other') if this_deduction.present?
            punishment = Companies::Salary.find_by("(? BETWEEN companies_salaries.from AND companies_salaries.to) AND (? = ANY(store_id)) AND (company_id = ?)", class_start_time, store_id, company_id)
            punishment = Companies::Salary.find_by("(? BETWEEN companies_salaries.from AND companies_salaries.to) AND (array_length(store_id,1) IS NULL)  AND (company_id = ?)", class_start_time, company_id) if punishment.blank?
            b_quota = punishment.try(:basic_class_number) || 0
            if timetable.try("absent?")
              deduction << { amount: (punishment.try(:absent) || 300) * salary / 100, reason: '旷课扣款', type: 'absent' }
            else
              deduction << { amount: (punishment.try(:late) || 50) * salary / 100, reason: '迟到扣款', type: 'late' } if timetable.try("late?")
              if [90, 120].exclude?(during) && standard_lesson_count < (coach_info.try(:standard_lesson) || 0)
                deduction << { amount: salary, reason: '包课费用', type: 'standard' }
                standard_lesson_count += 1
              else
                inspector = timetable.admission.try(:inspector)
                attendance = timetable.admission.try(:attendance) || -1
                basic_class_number = punishment.try(:basic_class_number) || 1
                basic_class_deduction = punishment.try(:basic_class_deduction) || 50
                basic_lesson_fee = punishment.try(:basic_lesson_fee) || 0
                if inspector.blank?
                  if attendance < basic_class_number
                    deduction << { type: 'attendance', amount: basic_class_deduction * salary / 100, number: attendance, reason: "登记未满#{basic_class_number}人" }
                    deduction << { type: 'basic', amount: -basic_lesson_fee, number: basic_class_number, reason: '基础课时费' }
                  end
                else
                  i_quota = inspector
                  if inspector < basic_class_number
                    deduction << { type: 'inspector', amount: basic_class_deduction * salary / 100, number: inspector, reason: "巡查未满#{basic_class_number}人" }
                    deduction << { type: 'basic', amount: -basic_lesson_fee, number: basic_class_number, reason: '基础课时费' }
                  end
                end
              end
            end
          when 'boutique'
            appointed = members + non_members
            real_pay = Order.joins(:appointment).where(status: :paid, appointments: { timetable_id: timetable.id }).sum(:pay_amount)
            brokerage_ratio = appointed > 7 ? 0.5 : 0.4
            salary = timetable.member_price * appointed * brokerage_ratio
            perquisite = real_pay * brokerage_ratio
          when 'personal'
            appointed = members + non_members
            real_pay = Order.joins(:appointment).where(status: :paid, appointments: { timetable_id: timetable.id }).sum(:pay_amount)
            brokerage_ratio = 0.4
            salary = timetable.member_price * appointed * brokerage_ratio
            perquisite = real_pay * brokerage_ratio
          when 'online'
            appointed = members + non_members
            real_pay = Order.joins(:appointment).where(status: :paid, appointments: { timetable_id: timetable.id }).sum(:pay_amount)
            brokerage_ratio = 0.7
            salary = timetable.price * appointed * brokerage_ratio
            perquisite = real_pay * brokerage_ratio
          else
            next
          end
          Payroll.create(
            timetable.slice(:company_id, :store_id, :course_id, :coach_id, :class_start_time, :class_end_time, :price, :market_price, :member_price).merge(
              timetable_id: timetable.id,
              company_name: timetable.company.name,
              city: timetable.store.city,
              store_name: timetable.store.name,
              course_name: (timetable.course.en_name + ' | ' + timetable.course.name),
              coach_name: timetable.coach.name,
              coach_employee_id: timetable.coach.try(:employee_id),
              quota: timetable.place,
              m_quota: members,
              nm_quota: non_members,
              r_quota: timetable.admission.try(:attendance) || -1,
              q_quota: timetable.queues.size,
              c_quota: 0,
              i_quota: i_quota,
              b_quota: b_quota,
              t_status: timetable.status,
              cr_fee: copyright,
              cl_fee: grade,
              subsidy: perquisite,
              salary: salary,
              deduction: deduction,
              status: salary.try(:status) || "pending",
              updated_at: timetable.signed_at
            )
          )
        }
      end
    end
  end
end
